﻿using HDSmartCommunity.DevicePlatform;
using HDSmartCommunity.Models;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace HDSmartCommunity.WebSockets
{
    public class ElevatorWebSocketMiddleware
    {
        public static List<WebSocket> _sockets = new List<WebSocket>();
        private readonly RequestDelegate _next;
        public ElevatorWebSocketMiddleware(RequestDelegate next)
        {
            this._next = next;
            // this._manage = manage;
        }
        public async Task Invoke(HttpContext context)
        {
            WebSocket currentSocket = null;
            try
            {
                if (!context.WebSockets.IsWebSocketRequest)
                {
                    await _next.Invoke(context);
                    return;
                }
                CancellationToken cancellationToken = context.RequestAborted;
                currentSocket = await context.WebSockets.AcceptWebSocketAsync();
                _sockets.Add(currentSocket);
                while (!currentSocket.CloseStatus.HasValue)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                    string response = await ReceiveStringAsync(currentSocket, cancellationToken);
                    if (response != null)
                    {
                        LiftStatus liftStatus = JsonConvert.DeserializeObject<LiftStatus>(response);

                        if (liftStatus.data != null && liftStatus.data.Count > 0)
                        {
                            foreach (var item in liftStatus.data)
                            {
                                ElevatorState elevatorState = new ElevatorState();
                                int deviceid = Convert.ToInt32(item.deviceID);
                                if (CEMSDeviceSerialData.elevators_state.TryGetValue(deviceid, out elevatorState))
                                {
                                    ElevatorState state = new ElevatorState();
                                    if (elevatorState.direction != item.direction && item.direction == 0)
                                    {
                                        //电梯停止前记录上一次运行方向状态
                                        state.direction_old = elevatorState.direction;
                                    }
                                    state.direction = item.direction;
                                    state.ladderid = deviceid;
                                    state.floor = item.pFloor;
                                    CEMSDeviceSerialData.elevators_state.Remove(deviceid);
                                    CEMSDeviceSerialData.elevators_state.Add(deviceid, state);
                                }
                                else
                                {
                                    elevatorState.direction = item.direction;
                                    elevatorState.ladderid = deviceid;
                                    elevatorState.floor = item.pFloor;
                                    CEMSDeviceSerialData.elevators_state.Add(deviceid, elevatorState);
                                }
                            }
                        }
                        LiftStatusReturn liftStatusReturn = new LiftStatusReturn();
                        liftStatusReturn.code = 0;
                        liftStatusReturn.method = "";
                        liftStatusReturn.req_id = liftStatus.req_id;
                    }
                }
                if (currentSocket != null && currentSocket.CloseStatus != null)
                    await currentSocket.CloseAsync(currentSocket.CloseStatus.Value, currentSocket.CloseStatusDescription, CancellationToken.None);
            }
            catch (Exception e)
            {
                _sockets.Remove(currentSocket);
            }
        }
        public static async Task<string> ReceiveStringAsync(WebSocket socket, CancellationToken ct)
        {
            var buffer = new ArraySegment<byte>(new byte[4 * 1024]);
            using (var ms = new MemoryStream())
            {
                WebSocketReceiveResult result;
                do
                {
                    ct.ThrowIfCancellationRequested();
                    try
                    {
                        result = await socket.ReceiveAsync(buffer, ct);
                        ms.Write(buffer.Array, buffer.Offset, result.Count);
                    }
                    catch (Exception e) { return null; }
                }
                while (!result.EndOfMessage);
                ms.Seek(0, SeekOrigin.Begin);
                if (result.MessageType != WebSocketMessageType.Text)
                {
                    return null;
                }
                using (var reader = new StreamReader(ms, Encoding.UTF8))
                {
                    return await reader.ReadToEndAsync();
                }
            }
        }

        public static void RemoveSocket(WebSocket webSocket)
        {
            _sockets.Remove(webSocket);
        }
    }
}
